package top.lshaci.learning.springboot.jpaquerydsl.core;

import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.querydsl.core.types.dsl.EntityPathBase;

/**
 * DslFromUtil
 *
 * @author lshaci
 * @since 1.0.0
 */
public class DslFromUtil {

    /**
     * 查询实体缓存
     */
    private static final SimpleCache<Class<?>, Object> FROM_OBJ_CACHE = new SimpleCache<>();


    /**
     * 获取查询实体
     *
     * @param fromClass 查询实体类
     * @param <Q>       查询实体类型
     * @return 查询实体
     */
    public static <Q extends EntityPathBase<?>> Q fromObj(Class<Q> fromClass) {
        verifyFromClass(fromClass);
        Q q = (Q) FROM_OBJ_CACHE.get(fromClass);
        if (q == null) {
            String fromFiledName = StrUtil.lowerFirst(fromClass.getSimpleName().substring(1));
            q = (Q) ReflectUtil.getStaticFieldValue(ReflectUtil.getField(fromClass, fromFiledName));
            FROM_OBJ_CACHE.put(fromClass, q);
        }
        return q;
    }

    /**
     * 获取查询实体
     *
     * @param dslQuery 查询实体类
     * @param <Q>      查询实体类型
     * @return 查询实体
     */
    public static <Q extends EntityPathBase<?>> Q fromObj(DslQuery dslQuery) {
        DslFrom dslFrom = dslQuery.getClass().getAnnotation(DslFrom.class);
        if (dslFrom == null) {
            throw DslException.build("请使用注解【{}】标记查询对象【{}】", DslFrom.class.getSimpleName(), dslQuery.getClass().getSimpleName());
        }
        Class<Q> fromClass = (Class<Q>) dslFrom.value();
        return fromObj(fromClass);
    }

    /**
     * 验证 fromClass 是否为 DSL插件编译生成的类
     *
     * @param fromClass DSL插件编译生成的类
     */
    public static void verifyFromClass(Class<? extends EntityPathBase<?>> fromClass) {
        if (fromClass == DslVoidEntity.class) {
            throw DslException.build("注解【{}】中的值, 请设置为DSL插件编译生成的类", DslFrom.class.getSimpleName());
        }
    }

}
